<template>
  <div class="my-process-designer">
    <div class="my-process-designer__header">
      <slot name="control-header"></slot>
      <template v-if="!$slots['control-header']">
        <div>
          <el-row style="margin-bottom: 10px">
            <el-col :span="this.isShowType !== 2?8:12">
              <!--              <a href="javascript:" @click="minioDownload()" title="保存为svg">minio下载</a>-->
              <el-button size="small" style="margin-top: 5px;" type="text">
                <span :style="styleValue1" @click="switchHandle(0)">{{ buttonValue1 }}</span>
              </el-button>
              <el-button size="small" style="margin-top: 5px;" type="text">
                <span :style="styleValue2" @click="switchHandle(1)">{{ buttonValue2 }}</span>
              </el-button>
              <el-button size="small" style="margin-top: 5px;" type="text"
                         v-if=" this.$route.params.id !== undefined && this.$route.params.id !== null && this.$route.params.id !== '' && this.isTabShow"
              >
                <span :style="styleValue3" @click="switchHandle(2)">{{ buttonValue3 }}</span>
              </el-button>
              <span
                v-if=" this.$route.params.id !== undefined && this.$route.params.id !== null && this.$route.params.id !== '' && this.isShowType !== 1 && this.isTabShow"
                style="font-size:15px;margin-left: 10px;color:red"
              > 评估分数:{{ this.score }}</span>
            </el-col>
            <el-col :span="8" style="text-align: right;" v-if="this.isShowType === 1">
              <el-button-group key="scale-control1" style="margin-top: 5px;"
                               v-if="this.$route.params.type === 1 || this.$route.params.type === '1'"
              >
                <el-tooltip effect="light" content="垂直居中">
                  <el-button :size="headerButtonSize" class="align align-center" icon="el-icon-s-data"
                             @click="elementsAlign('center')"
                  />
                </el-tooltip>
                <el-tooltip effect="light" content="水平居中">
                  <el-button :size="headerButtonSize" class="align align-middle" icon="el-icon-s-data"
                             @click="elementsAlign('middle')"
                  />
                </el-tooltip>
              </el-button-group>
              <el-button-group key="scale-control" style="margin-top: 5px;">
                <el-tooltip effect="light" content="缩小视图">
                  <el-button :size="headerButtonSize" :disabled="defaultZoom <= 0.3" icon="el-icon-zoom-out"
                             @click="processZoomOut()"
                  />
                </el-tooltip>
                <el-button :size="headerButtonSize">{{ Math.floor(this.defaultZoom * 10 * 10) + '%' }}</el-button>
                <el-tooltip effect="light" content="放大视图">
                  <el-button :size="headerButtonSize" :disabled="defaultZoom >= 3.9" icon="el-icon-zoom-in"
                             @click="processZoomIn()"
                  />
                </el-tooltip>
                <el-tooltip effect="light" content="重置视图并居中">
                  <el-button :size="headerButtonSize" icon="el-icon-c-scale-to-original" @click="processReZoom()"/>
                </el-tooltip>
              </el-button-group>
            </el-col>
            <el-col :span="6" style="text-align: right;" v-if="this.isShowType !== 2">
              <el-button size="small" @click="close()"
                         v-if="this.$route.params.type === 1 || this.$route.params.type === '1'"
              >返回
              </el-button>
              <el-button size="small" @click="onSave(0)" style="margin-top: 5px;"
                         v-if="this.$route.params.type === 1 || this.$route.params.type === '1'"
              >
                保存
              </el-button>
              <el-button style="margin-top: 5px;" size="small" type="primary" @click="onSave(1)"
                         v-if="(this.$route.params.type === 1 || this.$route.params.type === '1') && this.isAudit ===undefined"
              >提交
              </el-button>
            </el-col>
            <el-col :span="2" v-if="this.isShowType === 1" style="text-align: right;">
              <el-button size="small" v-if="buttonType" @click="hiddenSet(0)" style="margin-top: 5px;">隐藏</el-button>
              <el-button size="small" v-else @click="hiddenSet(1)" style="margin-top: 5px;">显示</el-button>
            </el-col>
          </el-row>
        </div>
      </template>
    </div>
    <!--提交表单-->
    <div v-show="this.isAudit !==undefined && isShowType===0">
      <el-card class="box-card">
        <div slot="header" class="clearfix">
          <h4 style="padding: 5px;">
            审批节点
            <el-button v-if="this.isAudit === true" size="mini" type="primary" @click="auditHandle(2)"
                       style="margin-left: 30px;"
            >同意
            </el-button>
            <el-button v-if="this.isAudit === true" size="mini" type="primary" @click="auditHandle(3)"
                       style="margin-left: 30px;"
            >拒绝
            </el-button>
          </h4>
        </div>
        <el-steps :active="isNode" align-center :process-status="processStatus">
          <el-step v-for="(item, index) in stepList" :key="index" :title="item.nodeName"
                   :description="(item.auditState === 0 || item.auditState ===1)
                    ?('审批人:'+item.auditName):('确认人:'+item.verifyUserName+',审批时间:'+item.updateTime)"
          ></el-step>
        </el-steps>
      </el-card>
    </div>
    <div v-show="isShowType === 0" style="overflow-y: auto;height: 100%">
      <el-form :rules="rules" ref="ruleForm" :model="dataFrom">
        <el-card class="box-card" style="margin-top: 10px">
          <div style="width: 150px; height: 10px; background-color: var(--primary-color);position:relative;top:-15px"></div>
          <div class="title20Class">
            <svg-icon icon-class="process" class="svgClass"/>
            流程信息
          </div>
          <el-divider content-position="left"></el-divider>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="流程名称 （注:最多50字）" prop="processName">
                <el-input size="small" v-model="dataFrom.processName" placeholder="请输入流程名称"
                          :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                ></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="所在业务分类" prop="businessTypeName">
                <el-cascader size="small" :options="businessOptions" clearable
                             v-model="dataFrom.businessTypeId" filterable style="width: 100%"
                             :props="{ value:'value',Label:'businessName',emitPath:false,checkStrictly: true  }"
                             :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                ></el-cascader>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="主办部门" prop="hostDeptId">
                <el-cascader size="small" :options="deptOptions" clearable
                             v-model="dataFrom.hostDeptId" filterable style="width: 100%"
                             :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                             :props="{ value:'deptId',Label:'deptName',emitPath:false,checkStrictly: true  }"
                ></el-cascader>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="责任部门职责">
                <el-input size="small" v-model="dataFrom.responsibilityDeptValue" placeholder="请输入责任部门职责"
                          :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                          type="textarea" :autosize="{ minRows: 1}"
                ></el-input>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="基层单位职责">
                <el-input v-model="dataFrom.grassrootsDeptValue" placeholder="请输入基层单位职责" size="small"
                          :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                          type="textarea" :autosize="{ minRows: 1}"
                ></el-input>
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="横向部门职责">
                <el-input v-model="dataFrom.transverseDeptValue" placeholder="请输入横向部门职责" size="small"
                          :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                          type="textarea" :autosize="{ minRows: 1}"
                ></el-input>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="20">
            <el-col :span="12">
              <el-form-item label="系统名称">
                <el-input size="small" type="textarea" v-model="dataFrom.systemName" clearable
                          placeholder="请输入系统名称" :autosize="{ minRows: 1}"
                          :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                />
              </el-form-item>
            </el-col>
            <el-col :span="12">
              <el-form-item label="系统地址">
                <el-input size="small" type="textarea" v-model="dataFrom.systemUrl" clearable
                          placeholder="请输入系统地址" :autosize="{ minRows: 1}"
                          :disabled="this.$route.params.type !== 1 && this.$route.params.type !== '1'"
                />
              </el-form-item>
            </el-col>
          </el-row>
        </el-card>
        <el-card class="box-card" style="margin-top: 10px">
          <el-row>
            <el-col :span="12">
              <div style="width: 150px; height: 10px; background-color: var(--primary-color);position:relative;top:-15px"></div>
              <div class="title20Class">
                <svg-icon icon-class="zhidu" class="svgClass"/>
                制度文件
              </div>
            </el-col>
            <el-col :span="12" style="text-align: right">
              <el-button style="float: right; padding: 5px 10px" type="text" @click="addDialog"
                         v-if="this.$route.params.type === 1 || this.$route.params.type === '1'"
              >新增
              </el-button>
              <el-button style="float: right; padding: 5px" type="text" @click="isDialog"
                         v-if="this.$route.params.type === 1 || this.$route.params.type === '1'"
              >选择
              </el-button>
            </el-col>
          </el-row>
          <el-divider content-position="left"></el-divider>
          <el-table :data="fileTable" size="mini" max-height="240" border fit>
            <el-table-column label="制度文号" align="center" key="systemNumber" prop="systemNumber"/>
            <el-table-column label="制度名称" align="center" key="systemName" prop="systemName"/>
            <el-table-column label="制度编号" align="center" key="systemCode" prop="systemCode"/>
            <!--            <el-table-column label="制度内容" align="center" key="systemPurpose" prop="systemPurpose"/>-->
            <el-table-column label="编制部门" align="center" key="superintendent" prop="superintendent" width="130px"/>
            <el-table-column label="签发日期" align="center" key="issueDate" prop="issueDate" width="130px"/>
            <el-table-column label="附件" align="center" key="name" prop="name" width="80px">
              <template slot-scope="scope">
                <a :href="scope.row.url" target="_blank"
                >{{ scope.row.name }}</a>
              </template>
            </el-table-column>
            <el-table-column label="操作" align="center" width="90px"
                             v-if="this.$route.params.type === 1 || this.$route.params.type === '1'"
            >
              <template slot-scope="{ row, $index }">
                <el-button size="mini" type="text" style="color: #448EF7" @click="getInfo(row)">详情
                </el-button>
                <el-button size="mini" type="text" style="color: #448EF7" @click="removeAttributes(row, $index)"
                >移除
                </el-button>
              </template>
            </el-table-column>
            <el-table-column label="操作" width="90px" v-else>
              <template slot-scope="{ row, $index }">
                <el-button size="mini" type="text" style="color: #448EF7" @click="getInfo(row)">详情
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-card>
      </el-form>
    </div>

    <el-dialog title="制度文件选择" :visible.sync="institutionOpen" append-to-body width="90%">
      <choose-institution-table @checkData="checkData" ref="chooseInstitutionTable"></choose-institution-table>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" type="primary" @click="deptSubmitForm">确 定</el-button>
        <el-button size="small" @click="deptCancel">取 消</el-button>
      </div>
    </el-dialog>
    <el-dialog title="新增制度" :visible.sync="institutionAddInfoOpen" append-to-body width="70%">
      <el-form ref="addInfo" :model="addInfo" label-width="120px" :rules="ruleInfos">
        <h4 style="padding: 5px;">基本信息</h4>
        <el-row>
          <el-col :span="12">
            <el-form-item label="制度文号:" prop="systemNumber">
              <el-input v-model="addInfo.systemNumber" clearable placeholder="请输入制度文号" size="small"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="制度名称:" prop="systemName">
              <el-input v-model="addInfo.systemName" clearable placeholder="请输入制度名称" size="small"/>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="制度编号:" prop="systemCode">
              <el-input v-model="addInfo.systemCode" clearable placeholder="请输入制度编号" size="small"/>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="编制部门:" prop="superintendent">
              <el-cascader size="small" :options="deptOptions" clearable
                           v-model="addInfo.superintendent" filterable style="width: 100%" placeholder="请选择编制部门"
                           :props="{ value:'deptId',Label:'deptName',emitPath:false,checkStrictly: true  }"
              ></el-cascader>
            </el-form-item>
          </el-col>
        </el-row>
        <!--        <el-row>-->
        <!--          <el-col :span="24">-->
        <!--            <el-form-item label="制度内容:" prop="systemPurpose">-->
        <!--              <el-input v-model="addInfo.systemPurpose" clearable placeholder="请输入制度内容" size="small"/>-->
        <!--            </el-form-item>-->
        <!--          </el-col>-->
        <!--        </el-row>-->
        <el-row>
          <el-col :span="12">
            <el-form-item label="签发日期:" prop="issueDate">
              <el-date-picker
                v-model="addInfo.issueDate"
                type="date"
                placeholder="请选择签发日期"
                value-format="yyyy-MM-dd"
              >
              </el-date-picker>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="文件上传:" prop="issueDate">
              <el-upload
                class="upload-demo"
                :action="uploadUrl"
                multiple
                :limit="1"
                :on-exceed="handleExceed"
                :on-success="handleAvatarSuccess"
                :before-upload="beforeAvatarUpload"
                :before-remove="beforeRemove"
                :file-list="fileList"
              >
                <el-button size="small" icon="el-icon-upload">点击上传</el-button>
              </el-upload>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" type="primary" @click="addInfoHandle">确 定
        </el-button>
        <el-button size="small" @click="institutionAddInfoOpen= false">取 消
        </el-button>
      </div>
    </el-dialog>
    <el-dialog title="制度文件详情" :visible.sync="institutionInfoOpen" append-to-body width="70%">
      <el-form ref="info" :model="info" label-width="120px">
        <h4 style="padding: 5px;">基本信息</h4>
        <el-row>
          <el-col :span="12">
            <el-form-item label="制度文号:" prop="description">
              {{ info.systemNumber }}
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="制度名称:" prop="activityId">
              {{ info.systemName }}
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="制度编号:" prop="event">
              {{ info.systemCode }}
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="编制部门:" prop="regulations">
              {{ info.superintendent }}
            </el-form-item>
          </el-col>
        </el-row>
        <!--        <el-row>-->
        <!--          <el-col :span="24">-->
        <!--            <el-form-item label="制度内容:" prop="systemPurpose">-->
        <!--              {{ info.systemPurpose }}-->
        <!--            </el-form-item>-->
        <!--          </el-col>-->
        <!--        </el-row>-->
        <el-row>
          <el-col :span="24">
            <el-form-item label="签发日期:" prop="prohibitedMatter">
              {{ info.issueDate }}
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="文件名称:">
              <a :href="info.url" target="_blank"
              >{{ info.name }}</a>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button size="small" @click="institutionInfoOpen= false">取 消</el-button>
      </div>
    </el-dialog>
    <!--提交表单-->
    <div style="width: 100%;background-color: #F2F4F5;" v-show="isShowType === 2">
      <el-card class="box-card" style="margin-top: 20px">
        <div style="width: 150px; height: 10px; background-color: var(--primary-color);position:relative;top:-15px"></div>
        <div class="title20Class">
          <svg-icon icon-class="pinggu" class="svgClass"/>
          流程评估
        </div>
        <el-divider content-position="left"></el-divider>
        <div v-for="(item, index) in cardDate" :key="index">
          <el-card class="box-card" style="margin-top: 20px">
            <div slot="header" class="clearfix">
              {{ item.title }}{{ item.proportion }}%
              <el-input-number v-model="item.score" controls-position="right" :min="0" :max="100"
                               placeholder="请输入指标权重" style="margin-left: 30px;width: 200px"
                               size="small"
              ></el-input-number>
            </div>
            <div class="text-item">
              {{ item.context }}
            </div>
          </el-card>
        </div>
        <div style="margin-top: 10px;text-align: center">
          <el-button size="small" type="primary" @click="add">确 定</el-button>
          <el-button size="small" @click="cancel">取 消</el-button>
        </div>
      </el-card>
    </div>
    <!--画布-->
    <div class="my-process-designer__container" v-show="isShowType === 1">
      <div class="my-process-designer__canvas" ref="bpmn-canvas"></div>
    </div>
  </div>
</template>

<script>
// 生产环境时优化
// const BpmnModeler = window.BpmnJS;
import BpmnModeler from 'bpmn-js/lib/Modeler'
import DefaultEmptyXML from './plugins/defaultEmpty'
// 翻译方法
import customTranslate from './plugins/translate/customTranslate'
import translationsCN from './plugins/translate/zh'
// 模拟流转流程
import tokenSimulation from 'bpmn-js-token-simulation'
// 标签解析构建器
// import bpmnPropertiesProvider from "bpmn-js-properties-panel/lib/provider/bpmn";
// 标签解析 Moddle
import camundaModdleDescriptor from './plugins/descriptor/camundaDescriptor.json'
import activitiModdleDescriptor from './plugins/descriptor/activitiDescriptor.json'
import flowableModdleDescriptor from './plugins/descriptor/flowableDescriptor.json'
// 标签解析 Extension
import camundaModdleExtension from './plugins/extension-moddle/camunda'
import activitiModdleExtension from './plugins/extension-moddle/activiti'
import flowableModdleExtension from './plugins/extension-moddle/flowable'
// 引入json转换与高亮
import convert from 'xml-js'
import ChooseDept from '@/plugins/package/tree/chooseDept'
import TreeSelect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'

import { businessControlTree } from '@/api/lc/business'
import { getProcessInfo, downLoadImage } from '@/api/workflow/model'
import chooseBusiness from '@/plugins/package/tree/chooseBusiness'
import { deptControlTree } from '@/api/system/user'
import { getScore, getEvaluateInfo, addOrUpdateEvaluateInfo } from '@/api/lc/evaluation'
import ChooseInstitutionTable from '@/plugins/package/tree/chooseInstitutionTable'
import { getDept } from '@/api/system/dept'
import { auditInfoList, audit } from '@/api/lc/processManagementList'
import { minioUpload } from '@/api/lc/minio'
import getJpeg from '@/utils/html-jpeg'
import html2canvas from 'html2canvas'
import { addInstitution } from '@/api/lc/institution'

export default {
  name: 'BpmnProcessDesigner',
  componentName: 'BpmnProcessDesigner',
  components: {
    ChooseDept,
    TreeSelect,
    chooseBusiness,
    ChooseInstitutionTable,
    html2canvas
  },
  props: {
    value: String, // xml 字符串
    processId: String,
    processName: String,
    translations: Object, // 自定义的翻译文件
    additionalModel: [Object, Array], // 自定义model
    moddleExtension: Object, // 自定义moddle
    onlyCustomizeAddi: {
      type: Boolean,
      default: false
    },
    onlyCustomizeModdle: {
      type: Boolean,
      default: false
    },
    simulation: {
      type: Boolean,
      default: true
    },
    keyboard: {
      type: Boolean,
      default: true
    },
    prefix: {
      type: String,
      default: 'flowable'
    },
    events: {
      type: Array,
      default: () => ['element.click']
    },
    headerButtonSize: {
      type: String,
      default: 'small',
      validator: value => ['default', 'medium', 'small', 'mini'].indexOf(value) !== -1
    },
    headerButtonType: {
      type: String,
      default: 'primary',
      validator: value => ['default', 'primary', 'success', 'warning', 'danger', 'info'].indexOf(value) !== -1
    }
  },
  data() {
    return {
      imageUrl: '',
      file: '',
      isNode: 0,
      isAudit: this.$route.params.isAudit,
      fileList: [],
      downLoadUrl: 'http://127.0.0.1:8089/file/',
      uploadUrl: process.env.VUE_APP_UPLOAD_URL,
      institutionInfoOpen: false,
      institutionOpen: false,
      institutionAddInfoOpen: false,
      isTabShow: false,
      correlationBaseOpen: false,
      chooseDeptOpen: false,
      defaultZoom: 1,
      previewModelVisible: false,
      simulationStatus: false,
      previewResult: '',
      previewType: 'xml',
      recoverable: false,
      revocable: false,
      styleValue1: 'color: #1890ff;font-size:15px;margin-left: 10px;',
      styleValue2: 'color: #999999;font-size:15px;margin-left: 10px;',
      styleValue3: 'color: #999999;font-size:15px;margin-left: 10px;',
      buttonValue1: '❶基础设置',
      buttonValue2: '②流程设置',
      buttonValue3: '③流程评估',
      buttonType: true,
      isShowType: 0,
      dataFrom: {
        processName: '',
        businessTypeId: '',
        businessTypeIds: '',
        businessTypeName: '',
        hostDeptId: '',
        hostDeptIds: '',
        hostDeptName: '',
        responsibilityDeptValue: '',
        grassrootsDeptValue: '',
        transverseDeptValue: '',
        description: '',
        xml: '',
        processAuditType: '',
        systemName: '',
        systemUrl: ''
      },
      ruleInfos: {
        systemNumber: [
          { required: true, message: '请输入制度名称', trigger: 'blur' }
        ],
        systemCode: [
          { required: true, message: '请输入制度编号', trigger: 'blur' }
        ],
        systemNo: [
          { required: true, message: '请输入制度文号', trigger: 'blur' }
        ],
        superintendent: [
          { required: true, message: '请输入制度文号', trigger: 'blur' }
        ],
        issueDate: [
          { required: true, message: '请输入签发日期', trigger: 'blur' }
        ]
      },
      rules: {
        processName: [
          { required: true, message: '请输入流程名称', trigger: 'blur' }
        ],
        businessTypeName: [
          { required: true, message: '请选择所在业务分类', trigger: 'blur' }
        ],
        hostDeptId: [
          { required: true, message: '请选择主办部门', trigger: 'blur' }
        ],
        responsibilityDeptValue: [
          { required: true, message: '请输入责任部门职责', trigger: 'blur' }
        ],
        description: [
          { required: true, message: '请输入流程说明', trigger: 'blur' }
        ]
      },
      hostDeptName: '',
      hostDeptId: '',
      // 树选项
      options: [],
      deptOptions: [],
      businessOptions: [],
      cardDate: [],
      score: 0.00,
      fileTable: [],
      info: {},
      addInfo: {
        systemNumber: '',
        systemCode: '',
        systemNo: '',
        superintendent: '',
        issueDate: '',
        systemPurpose: '',
        name: '',
        url: ''
      },
      multipleSelection: [],
      stepList: [],
      approveId: this.$route.params.approveId,
      processStatus: ''
    }
  },
  computed: {
    additionalModules() {
      const Modules = []
      // 仅保留用户自定义扩展模块
      if (this.onlyCustomizeAddi) {
        if (Object.prototype.toString.call(this.additionalModel) === '[object Array]') {
          return this.additionalModel || []
        }
        return [this.additionalModel]
      }

      // 插入用户自定义扩展模块
      if (Object.prototype.toString.call(this.additionalModel) === '[object Array]') {
        Modules.push(...this.additionalModel)
      } else {
        this.additionalModel && Modules.push(this.additionalModel)
      }

      // 翻译模块
      const TranslateModule = {
        translate: ['value', customTranslate(this.translations || translationsCN)]
      }
      Modules.push(TranslateModule)

      // 模拟流转模块
      if (this.simulation) {
        Modules.push(tokenSimulation)
      }

      // 根据需要的流程类型设置扩展元素构建模块
      // if (this.prefix === "bpmn") {
      //   Modules.push(bpmnModdleExtension);
      // }
      if (this.prefix === 'camunda') {
        Modules.push(camundaModdleExtension)
      }
      if (this.prefix === 'flowable') {
        Modules.push(flowableModdleExtension)
      }
      if (this.prefix === 'activiti') {
        Modules.push(activitiModdleExtension)
      }

      return Modules
    },
    moddleExtensions() {
      const Extensions = {}
      // 仅使用用户自定义模块
      if (this.onlyCustomizeModdle) {
        return this.moddleExtension || null
      }

      // 插入用户自定义模块
      if (this.moddleExtension) {
        for (let key in this.moddleExtension) {
          Extensions[key] = this.moddleExtension[key]
        }
      }

      // 根据需要的 "流程类型" 设置 对应的解析文件
      if (this.prefix === 'activiti') {
        Extensions.activiti = activitiModdleDescriptor
      }
      if (this.prefix === 'flowable') {
        Extensions.flowable = flowableModdleDescriptor
      }
      if (this.prefix === 'camunda') {
        Extensions.camunda = camundaModdleDescriptor
      }

      return Extensions
    }
  },
  mounted() {
    this.initBpmnModeler()
    this.createNewDiagram(this.value)
    this.$once('hook:beforeDestroy', () => {
      if (this.bpmnModeler) this.bpmnModeler.destroy()
      this.$emit('destroy', this.bpmnModeler)
      this.bpmnModeler = null
    })
    setTimeout(() => {
      if (this.$route.params.type === 0 && this.$route.params.isAudit !== true) {
        this.isShowType = 1
        this.switchHandle(1)
      }
    }, 500)
  },
  created() {
    this.getProcessInfo()
    this.evaluateInfo()
  },
  methods: {
    // 上传文件
    handleAvatarSuccess(res, file) {
      if (file.response.code === 200) {
        this.fileList.push({ 'name': file.name, 'url': file.response.data })
        this.addInfo.name = file.name
        this.addInfo.url = file.response.data
      }
    },
    // 文件校验
    beforeAvatarUpload(file) {
      // const fileName = file.name;
      // const fileType = fileName.substring(fileName.lastIndexOf('.'));
      // if(fileType !== '.docx' && fileType !== '.doc'){
      //   this.$message.warning(`请上传word文件!`)
      //   return false
      // }
    },
    // 文件个数超出
    handleExceed(files, fileList) {
      this.$message.warning(`当前限制选择 1 个文件，本次选择了 ${files.length} 个文件，共选择了 ${files.length + fileList.length} 个文件`)
    },
    beforeRemove(file, fileList) {
      const result = new Promise((resolve, reject) => {
        this.$confirm('此操作将永久删除该文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            this.fileList = []
            this.addInfo.fileUrl = []
            // 请求删除接口
          })
          .catch(() => {
            reject(false)
          })
      })
      return result
    },
    add() {
      addOrUpdateEvaluateInfo({
        processId: this.$route.params.id,
        contextJson: JSON.stringify(this.cardDate)
      }).then(res => {
        this.$modal.msgSuccess('操作成功')
        this.$store.dispatch('tagsView/delView', this.$route)
        this.$router.go(-1)
      })
    },
    cancel() {
      this.$store.dispatch('tagsView/delView', this.$route)
      this.$router.go(-1)
    },
    /** 查询部门下拉树结构 */
    getDeptTree() {
      deptControlTree().then(response => {
        this.deptOptions = response.data
      })
    },
    /**
     * 流程树
     */
    businessList() {
      businessControlTree().then(response => {
        this.businessOptions = response.data
      })
    },
    // 查询流程信息
    getProcessInfo() {
      let id = this.$route.params.id
      if (id !== undefined && this.$route.params.id !== null && this.$route.params.id !== '') {
        getProcessInfo(id).then(data => {
          this.dataFrom = data.data
          if (data.data.institution != null) {
            this.fileTable = JSON.parse(data.data.institution)
          }
          this.createNewDiagram(data.data.bpmnXml)
          this.getScoreInfo()
          if (this.isAudit !== undefined) {
            this.getSetInfo()
          }
        })
      }
    },
    getSetInfo() {
      auditInfoList({ processId: this.dataFrom.processId, processVersion: this.dataFrom.processVersion }).then(res => {
        this.stepList = res.data
        for (let i = 0; i < this.stepList.length; i++) {
          if (this.stepList[i].auditState >= 1) {
            if (this.stepList[i].auditState === 3) {
              this.processStatus = 'error'
              this.isNode = i
            } else {
              this.isNode = i
            }
          }
          if (i === this.stepList.length - 1 && this.stepList[i].auditState === 2) {
            this.isNode = i + 1
          }
        }
      })
    },
    // 提交保存
    async onSave(type) {
      return new Promise(async(resolve, reject) => {
        if (this.bpmnModeler == null) {
          reject()
        }
        let data = {}
        await this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
          this.dataFrom.xml = xml
          this.dataFrom.processAuditType = type
          if (this.fileTable.length > 0) {
            data = Object.assign(this.dataFrom, {
              'institution': JSON.stringify(this.fileTable)
            })
          } else {
            data = this.dataFrom
            resolve(xml)
          }
        })
        // await this.createNewDiagram(data.xml)
        //
        const elementRegistry = this.bpmnModeler.get('elementRegistry')
        // 获取所有的节点
        let i = 1
        // 请求后台获取节点顺序
        await downLoadImage({ 'bpmnXml': data.xml }).then(res => {
          console.log('res', res)
          for (let key in elementRegistry._elements) {
            let node = elementRegistry._elements[key]
            let element = node.element
            console.log('element.type', element.type)
            if (element.type === 'bpmn:StartEvent' || element.type === 'bpmn:Task' ||
              element.type === 'bpmn:UserTask' || element.type === 'bpmn:EndEvent' ||
              element.type === 'bpmn:ReceiveTask' || element.type === 'bpmn:ScriptTask') {
              let name = element.businessObject ? element.businessObject.name : undefined
              let id = element.businessObject ? element.businessObject.id : undefined
              console.log('res.data[id]', res.data[id])
              const modeling = this.bpmnModeler.get('modeling')
              console.log('modeling', modeling)
              // modeling.updateLabel(element, name)
              let attrObj = { 'name': res.data[id] }
              console.log('this.element -----------', element)
              console.log('attrObj', attrObj)
              modeling.updateProperties(element, attrObj)
              console.log(' modeling.updateProperties(element, attrObj)', modeling.updateProperties(element, attrObj))
              console.log('name', name)
              console.log('id', id)
              i++
            }
          }
        })

        // 截图流程页面
        await this.minioDownload()

        // 如果图片需要formData格式,就自己组装一下,主要看后台需要什么参数
        const formData = new FormData()
        formData.append('file', this.file)
        await minioUpload(formData).then(res => {
          console.log('res.data', res.data)
          this.imageUrl = res.data
          data.processImageUrl = this.imageUrl
          console.log('data.processImageUrl', data.processImageUrl)
          this.$emit('save', data)
        })
      })
    },
    // 隐藏基础信息
    hiddenSet(type) {
      const key = document.getElementsByClassName('process-panel__container process-panel')[0]
      if (type === 0) {
        console.log('隐藏')
        key.setAttribute('hidden', true)
        this.buttonType = false
      } else {
        console.log('显示')
        key.removeAttribute('hidden')
        this.buttonType = true
      }
    },
    // 切换页面
    switchHandle(type) {
      const key = document.getElementsByClassName('djs-palette two-column open')[0]
      if (key.length !== 0 && this.$route.params.type == 0) {
        key.setAttribute('hidden', true)
      }
      const key1 = document.getElementsByClassName('bjs-powered-by')[0]
      if (key1.length !== 0) {
        key1.setAttribute('hidden', true)
      }
      this.isShowType = type
      if (type === 0) {
        this.styleValue1 = 'color: #1890ff;font-size:15px;margin-left: 10px;'
        this.styleValue2 = 'color: #999999;font-size:15px;margin-left: 10px;'
        this.styleValue3 = 'color: #999999;font-size:15px;margin-left: 10px;'
        this.buttonValue1 = '❶基础设置'
        this.buttonValue2 = '②流程设置'
        this.buttonValue3 = '③流程评估'
      } else if (type === 1) {
        this.styleValue1 = 'color: #999999;font-size:15px;margin-left: 10px;'
        this.styleValue2 = 'color: #1890ff;font-size:15px;margin-left: 10px;'
        this.styleValue3 = 'color: #999999;font-size:15px;margin-left: 10px;'
        this.buttonValue1 = '①基础设置'
        this.buttonValue2 = '❷流程设置'
        this.buttonValue3 = '③流程评估'
      } else {
        this.styleValue1 = 'color: #999999;font-size:15px;margin-left: 10px;'
        this.styleValue2 = 'color: #999999;font-size:15px;margin-left: 10px;'
        this.styleValue3 = 'color: #1890ff;font-size:15px;margin-left: 10px;'
        this.buttonValue1 = '①基础设置'
        this.buttonValue2 = '②流程设置'
        this.buttonValue3 = '❸流程评估'
        this.evaluateInfo()
      }
      this.$emit('childShowType', this.isShowType)
    },
    evaluateInfo() {
      if (this.$route.params.id !== undefined && this.$route.params.id !== null && this.$route.params.id !== '') {
        getEvaluateInfo(this.$route.params.id).then(res => {
          if (res.msg !== '暂无数据') {
            this.isTabShow = true
          }
          this.cardDate = res.data
        })
      }
    },
    initBpmnModeler() {
      if (this.bpmnModeler) return
      if (this.$route.params.type === 0 || this.$route.params.type === '0') {
        this.additionalModules.push({
          labelEditingProvider: ['value', ''],
          bendpoints: ['value', {}], //禁用连线拖动
          moveCanvas: ['value', ''], //禁用拖动整个流程图
          move: ['value', ''] //禁用单个图形拖动
        })
      }

      this.bpmnModeler = new BpmnModeler({
        container: this.$refs['bpmn-canvas'],
        keyboard: this.keyboard ? { bindTo: document } : null,
        additionalModules: this.additionalModules,
        moddleExtensions: this.moddleExtensions
      })
      this.$emit('init-finished', this.bpmnModeler)
      this.initModelListeners()
      this.businessList()
      this.getDeptTree()
    },
    initModelListeners() {
      const EventBus = this.bpmnModeler.get('eventBus')
      const that = this
      // 注册需要的监听事件, 将. 替换为 - , 避免解析异常
      this.events.forEach(event => {
        EventBus.on(event, function(eventObj) {
          let eventName = event.replace(/\./g, '-')
          let element = eventObj ? eventObj.element : null
          that.$emit(eventName, element, eventObj)
          that.$emit('event', eventName, element, eventObj)
        })
      })
      // 监听图形改变返回xml
      EventBus.on('commandStack.changed', async event => {
        try {
          this.recoverable = this.bpmnModeler.get('commandStack').canRedo()
          this.revocable = this.bpmnModeler.get('commandStack').canUndo()
          let { xml } = await this.bpmnModeler.saveXML({ format: true })
          this.$emit('commandStack-changed', event)
          this.$emit('input', xml)
          this.$emit('change', xml)
        } catch (e) {
          console.error(`[Process Designer Warn]: ${e.message || e}`)
        }
      })
      // 监听视图缩放变化
      this.bpmnModeler.on('canvas.viewbox.changed', ({ viewbox }) => {
        this.$emit('canvas-viewbox-changed', { viewbox })
        const { scale } = viewbox
        this.defaultZoom = Math.floor(scale * 100) / 100
      })
    },
    /* 创建新的流程图 */
    async createNewDiagram(xml) {
      // 将字符串转换成图显示出来
      let newId = this.processId || `Process_${new Date().getTime()}`
      let newName = this.processName || `平台_${new Date().getTime()}`
      let xmlString = xml || DefaultEmptyXML(newId, newName, this.prefix)
      try {
        let { warnings } = await this.bpmnModeler.importXML(xmlString)
        if (warnings && warnings.length) {
          warnings.forEach(warn => console.warn(warn))
        }
      } catch (e) {
        console.error(`[Process Designer Warn]: ${e.message || e}`)
      }
    },

    // 下载流程图到本地
    async downloadProcess(type, name) {
      try {
        const _this = this
        // 按需要类型创建文件并下载
        if (type === 'xml' || type === 'bpmn') {
          const { err, xml } = await this.bpmnModeler.saveXML()
          // 读取异常时抛出异常
          if (err) {
            console.error(`[Process Designer Warn ]: ${err.message || err}`)
          }
          let { href, filename } = _this.setEncoded(type.toUpperCase(), name, xml)
          downloadFunc(href, filename)
        } else {
          const { err, svg } = await this.bpmnModeler.saveSVG()
          // 读取异常时抛出异常
          if (err) {
            return console.error(err)
          }
          let { href, filename } = _this.setEncoded('SVG', name, svg)
          downloadFunc(href, filename)
        }
      } catch (e) {
        console.error(`[Process Designer Warn ]: ${e.message || e}`)
      }

      // 文件下载方法
      function downloadFunc(href, filename) {
        if (href && filename) {
          let a = document.createElement('a')
          a.download = filename //指定下载的文件名
          a.href = href //  URL对象
          a.click() // 模拟点击
          URL.revokeObjectURL(a.href) // 释放URL 对象
        }
      }
    },

    // 根据所需类型进行转码并返回下载地址
    setEncoded(type, filename = 'diagram', data) {
      const encodedData = encodeURIComponent(data)
      return {
        filename: `${filename}.${type}`,
        href: `data:application/${type === 'svg' ? 'text/xml' : 'bpmn20-xml'};charset=UTF-8,${encodedData}`,
        data: data
      }
    },

    // 加载本地文件
    importLocalFile() {
      const that = this
      const file = this.$refs.refFile.files[0]
      const reader = new FileReader()
      reader.readAsText(file)
      reader.onload = function() {
        let xmlStr = this.result
        that.createNewDiagram(xmlStr)
      }
    },
    /* ------------------------------------------------ refs methods ------------------------------------------------------ */
    downloadProcessAsXml() {
      this.downloadProcess('xml')
    },
    downloadProcessAsBpmn() {
      this.downloadProcess('bpmn')
    },
    downloadProcessAsSvg() {
      this.downloadProcess('svg')
    },
    processSimulation() {
      this.simulationStatus = !this.simulationStatus
      this.simulation && this.bpmnModeler.get('toggleMode').toggleMode()
    },
    processRedo() {
      this.bpmnModeler.get('commandStack').redo()
    },
    processUndo() {
      this.bpmnModeler.get('commandStack').undo()
    },
    processZoomIn(zoomStep = 0.1) {
      let newZoom = Math.floor(this.defaultZoom * 100 + zoomStep * 100) / 100
      if (newZoom > 4) {
        throw new Error('[Process Designer Warn ]: The zoom ratio cannot be greater than 4')
      }
      this.defaultZoom = newZoom
      this.bpmnModeler.get('canvas').zoom(this.defaultZoom)
    },
    processZoomOut(zoomStep = 0.1) {
      let newZoom = Math.floor(this.defaultZoom * 100 - zoomStep * 100) / 100
      if (newZoom < 0.2) {
        throw new Error('[Process Designer Warn ]: The zoom ratio cannot be less than 0.2')
      }
      this.defaultZoom = newZoom
      this.bpmnModeler.get('canvas').zoom(this.defaultZoom)
    },
    processZoomTo(newZoom = 1) {
      if (newZoom < 0.2) {
        throw new Error('[Process Designer Warn ]: The zoom ratio cannot be less than 0.2')
      }
      if (newZoom > 4) {
        throw new Error('[Process Designer Warn ]: The zoom ratio cannot be greater than 4')
      }
      this.defaultZoom = newZoom
      this.bpmnModeler.get('canvas').zoom(newZoom)
    },
    processReZoom() {
      this.defaultZoom = 1
      this.bpmnModeler.get('canvas').zoom('fit-viewport', 'auto')
    },
    processRestart() {
      this.recoverable = false
      this.revocable = false
      this.createNewDiagram(null).then(() => this.bpmnModeler.get('canvas').zoom(1, 'auto'))
    },
    elementsAlign(align) {
      const Align = this.bpmnModeler.get('alignElements')
      const Selection = this.bpmnModeler.get('selection')
      const SelectedElements = Selection.get()
      if (!SelectedElements || SelectedElements.length <= 1) {
        this.$message.warning('请按住 Ctrl 键选择多个元素对齐')
        return
      }
      this.$confirm('自动对齐可能造成图形变形，是否继续？', '警告', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => Align.trigger(SelectedElements, align))
    },
    /*-----------------------------    方法结束     ---------------------------------*/
    previewProcessXML() {
      this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
        this.previewResult = xml
        this.previewType = 'xml'
        this.previewModelVisible = true
      })
    },
    previewProcessJson() {
      this.bpmnModeler.saveXML({ format: true }).then(({ xml }) => {
        this.previewResult = convert.xml2json(xml, { spaces: 2 })
        this.previewType = 'json'
        this.previewModelVisible = true
      })
    },

    /**
     * 部门弹出
     */
    chooseDeptHandle() {
      this.chooseDeptOpen = true
    },
    /**
     * 部门子页面传参到父页面
     */
    deptValue(data) {
      this.hostDeptName = data.label
      this.hostDeptId = data.id
    },
    // 制度文件确认
    deptSubmitForm() {
      this.institutionOpen = false
      if (this.fileTable.length === 0) {
        this.fileTable = this.multipleSelection
        return
      }
      for (let i = 0; i < this.multipleSelection.length; i++) {
        let bo = false
        for (let b = 0; b < this.fileTable.length; b++) {
          if (this.multipleSelection[i].systemId === this.fileTable[b].systemId) {
            bo = false
            break
          }
          bo = true
        }
        if (bo) {
          this.fileTable.push(this.multipleSelection[i])
        }
      }

    },
    /**
     * 主办部门选择-取消
     */
    deptCancel() {
      this.institutionOpen = false
    },
    /** 转换结构 */
    normalizer(node) {
      if (node.children && !node.children.length) {
        delete node.children
      }
      return {
        id: node.businessId,
        label: node.businessName,
        children: node.children
      }
    },
    // 弹出显示
    isDialog() {
      this.institutionOpen = true
      this.$nextTick(() => {
        this.$refs.chooseInstitutionTable.init()
      })
    },
    addInfoHandle() {
      this.$refs['addInfo'].validate(valid => {
        if (valid) {
          getDept(this.addInfo.superintendent).then(response => {
            this.addInfo.superintendent = response.data.deptName
            addInstitution(this.addInfo).then(res => {
              if (res.code === 200) {
                this.institutionAddInfoOpen = false
                this.fileTable.push(this.addInfo)
                this.$message.success('操作成功')
              }
            })
          })
        }
      })
    },
    addDialog() {
      this.institutionAddInfoOpen = true
      this.addInfo = {
        systemNumber: '',
        systemCode: '',
        systemNo: '',
        superintendent: '',
        issueDate: '',
        systemPurpose: '',
        name: '',
        url: ''
      }
      this.fileList = []
      this.$nextTick(() => {
        this.$refs['addInfo'].clearValidate()
      })
    },
    // 子页面回传参数
    checkData(data) {
      this.multipleSelection = data
    },
    /** 关闭按钮 */
    close() {
      this.$store.dispatch('tagsView/delView', this.$route)
      this.$router.go(-1)
    },
    getScoreInfo() {
      getScore(this.$route.params.id).then(res => {
        this.score = res.data
      })
    },
    // 获取详情
    getInfo(info) {
      this.institutionInfoOpen = true
      this.info = info
    },
    // 移除文件
    removeAttributes(attr, index) {
      this.$confirm('确定移除当前文件么？', '提示', {
        confirmButtonText: '确 认',
        cancelButtonText: '取 消'
      })
        .then(() => {
          this.fileTable.splice(index, 1)
        })
        .catch(() => console.info('操作取消'))
    },
    //
    auditHandle(type) {
      this.$prompt('请输入审批意见', '审批', {
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      }).then(({ value }) => {
        audit({ approveId: this.approveId, type: type, context: value }).then(res => {
          if (res.code === 200) {
            this.$store.dispatch('tagsView/delView', this.$route)
            this.$router.go(-1)
          }
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '取消审批'
        })
      })
    },
    // 第一种调用后台接口form-data传file文件
    async minioDownload() {
      // 切换中流程设置页面
      await this.switchHandle(1)
      await this.hiddenSet(0)
      await this.processReZoom()
      const key = document.getElementsByClassName('djs-palette two-column open')[0]
      if (key.length !== 0) {
        key.setAttribute('hidden', true)
      }
      // 页面元素转图片
      // 第一个参数是需要生成截图的元素,第二个是自己需要配置的参数,宽高等
      let ref = document.getElementsByClassName('djs-container')[0]
      let ia
      let mime
      await html2canvas(ref, {}).then((canvas) => {
        // 把生成的base64位图片上传到服务器,生成在线图片地址
        let urlData = canvas.toDataURL('image/png')
        const arr = urlData.split(',')
        mime = arr[0].match(/:(.*?);/)[1]
        const bytes = atob(arr[1])
        let n = bytes.length
        ia = new Uint8Array(n)
        while (n--) {
          ia[n] = bytes.charCodeAt(n)
        }
      })
      this.file = new File([ia], 'jpeg', { type: mime })
      await this.hiddenSet(1)
      if (key.length !== 0) {
        key.removeAttribute('hidden')
      }
    },
    // 图片上传服务器
    sendUrl(file) {
      // 如果图片需要formData格式,就自己组装一下,主要看后台需要什么参数
      const formData = new FormData()
      formData.append('file', file)
      minioUpload(formData).then(res => {
        this.imageUrl = res.data
      })
    }
  }
}
</script>

<style scoped>

</style>
